package org.mtdownload.app;

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.parser.ParserDelegator;
import javax.swing.text.MutableAttributeSet;

import org.mtdownload.dialogs.AddDownloadDialog;
import org.mtdownload.dialogs.checklist.CheckListDialog;
import org.mtdownload.download.DownloadManager;
import org.mtdownload.download.DownloadTask;
import org.mtdownload.download.DownloadTaskPropertiesChanged;
import org.mtdownload.listview.DownloadsListSelectionListener;
import org.mtdownload.listview.MTDownloadListView;
import org.mtdownload.utils.PreferencesManager;

public class MTDownloadContentPane extends JPanel {

	private static final long serialVersionUID = 4048790148160174384L;
	
	private JSplitPane splitPane=new JSplitPane(JSplitPane.VERTICAL_SPLIT);
	private JToolBar toolBar=new JToolBar();
	private MTDownloadListView listView=new MTDownloadListView();
	private InfoTabsView infoView=new InfoTabsView();
	
	private JToggleButton start_pauseDldButton=null;
	private ImageIcon pauseDldIcon=null;
	private ImageIcon startDldIcon=null;

	private DownloadTask currentlySelectedTask=null;
	
	public MTDownloadContentPane() {
		super();
		init();
	}
	
	private void init(){
		setLayout(new BorderLayout());
		setupToolbar();		
		splitPane.setTopComponent(listView);
		splitPane.setBottomComponent(infoView);
		splitPane.setDividerLocation(PreferencesManager.getSplitDividerLocation());
		add(toolBar,BorderLayout.NORTH);
		add(splitPane,BorderLayout.CENTER);
	}
	
	private void setupToolbar(){
		ImageIcon addDldIcon=new ImageIcon(MTDownloadContentPane.class.getResource(Icons.ADD_DLD));
		JButton addDldButton=new JButton(addDldIcon);
		addDldButton.setToolTipText("Add download");
		addDldButton.setMnemonic(KeyEvent.VK_N);
		addDldButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				newDownload();
			}
		});
		startDldIcon=new ImageIcon(MTDownloadContentPane.class.getResource(Icons.START_DLD));
		pauseDldIcon=new ImageIcon(MTDownloadContentPane.class.getResource(Icons.PAUSE_DLD));
		start_pauseDldButton=new JToggleButton(startDldIcon,false);
		start_pauseDldButton.setToolTipText("Start download");
		start_pauseDldButton.setSelectedIcon(pauseDldIcon);
		ImageIcon removeDldIcon=new ImageIcon(MTDownloadContentPane.class.getResource(Icons.REMOVE_DLD));
		start_pauseDldButton.addItemListener(new ItemListener(){
			public void itemStateChanged(ItemEvent e) {
				if(currentlySelectedTask==null)return;				
				if(e.getStateChange()==ItemEvent.SELECTED){
					DownloadManager.startDownload(currentlySelectedTask);					
				}else{					
					currentlySelectedTask.stopDownload();
				}
				
			}
		});
		final JButton removeDldButton=new JButton(removeDldIcon);
		removeDldButton.setToolTipText("Remove download");
		removeDldButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				removeSelectedDownload();
			}
		});		
		Image openUrlIcon=new ImageIcon(MTDownloadContentPane.class.getResource(Icons.OPEN_URLS_FILE)).getImage();
		JButton addDownloadsURLSFromFile=new JButton(new ImageIcon(openUrlIcon.getScaledInstance(16,16,Image.SCALE_SMOOTH)));
		addDownloadsURLSFromFile.setToolTipText("Load URL's from file/URL");
		addDownloadsURLSFromFile.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				loadURLSFromFile();
			}
		});		
		toolBar.add(addDldButton);
		toolBar.add(addDownloadsURLSFromFile);
		toolBar.add(start_pauseDldButton);
		toolBar.add(removeDldButton);
		removeDldButton.setEnabled(false);
		start_pauseDldButton.setEnabled(false);
		
		listView.addDownloadListSelectionListener(new DownloadsListSelectionListener(){
			public void downloadsSelected(int[] rows) {
				removeDldButton.setEnabled(rows!=null&&rows.length>0);
				start_pauseDldButton.setEnabled(rows!=null&&rows.length>0);
				if(rows!=null&&rows.length>0){
					int first=rows[0];
					currentlySelectedTask=DownloadManager.getDownloadTaskAt(first);
					changeButtonsState();
				}
			}
		});
		listView.addDownloadListSelectionListener(infoView.getDownloadsListSelectionListener());
		DownloadManager.addDownloadTaskPropertiesChangedListener(new DownloadTaskPropertiesChanged(){
			public void propertiesChanged(DownloadTask task) {
				if(task.equals(currentlySelectedTask)){
					 changeButtonsState();
				}
			}
		});		
	}
	
	protected void loadURLSFromFile() {
		AddDownloadDialog dialog=new AddDownloadDialog(JOptionPane.getFrameForComponent(this),"Add Downloads from File/URL",true,true);
		dialog.setLocationRelativeTo(this);
		dialog.setVisible(true);
		DownloadTask task=dialog.getDownloadTask();
		if(task!=null){
			URL url=null;
			try {
				url=new URL(task.getUrl());
			} catch (MalformedURLException e) {/*ignored*/}
			if(url==null){
				//the url was not good. lets see if its a file we're talking about
				File urlFile=new File(task.getUrl());
				if(urlFile.exists()){
					try {
						url=urlFile.toURL();
					} catch (MalformedURLException e) {/*ignored*/}
				}
			}
			if(url==null){
				//still null .... cant find the file and the text isn't an URL
				JOptionPane.showMessageDialog(this,"<html>The resource <i>"+task.getUrl()+"</i> cannot be found.</html>","Error",JOptionPane.ERROR_MESSAGE);
				return;
			}
			List<String> urls=null;
			setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
			try {
				URLConnection con=url.openConnection();
				String contentType=con.getContentType();				
				//we recognize text/plain and text/html content types
				if(contentType.contains("text/plain")){
					urls=parsePlainFile(con);
				}
				if(contentType.contains("text/html")){
					urls=parseHtmlFile(con);
				}				
			} catch (IOException e) {
				e.printStackTrace();
			}
			setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			if(urls==null){
				JOptionPane.showMessageDialog(this,"The file  "+task.getUrl()+" could not be parsed. Make sure its a plain text or HTML file or resource.","Error",JOptionPane.ERROR_MESSAGE);
				return;
			}
			List selectedUrls=CheckListDialog.showCheckListDialog(this,"Select the files to download","Select files",urls);
			if(selectedUrls!=null){
				for(int i=0;i<selectedUrls.size();i++){
//			DownloadManager.addDownloadTask(task);
//			DownloadManager.saveDownloadList(PreferencesManager.getDownloadListDatabase());
					
				}
			}
		}		
	}

	private List<String> parseHtmlFile(final URLConnection con) throws IOException {
		final List<String> urls=new ArrayList<String>();
		BufferedReader in=new BufferedReader(new InputStreamReader(con.getInputStream()));
		HTMLEditorKit.ParserCallback callback = 
			new HTMLEditorKit.ParserCallback () {
			public void handleStartTag(HTML.Tag tag, MutableAttributeSet attrSet, int pos) {
				if(tag==HTML.Tag.A){
					//get the HREF attribute. If it's and valid url add it to the list
					String href=(String)attrSet.getAttribute(HTML.Attribute.HREF);
					try {
						URL testURL=new URL(href);
						//if we get here, it means the URL is ok
						//add it to the list
						urls.add(testURL.toString());
						return;
					} catch (MalformedURLException e) {/*ignored*/}	
					//the url is not OK. could it be relative?
					try {
						URL testURL=new URL(con.getURL(),href);
						//if we get here, it means the URL is ok
						//add it to the list
						urls.add(testURL.toString());
					} catch (MalformedURLException e) {/*ignored*/}						
				}
			}
		};				
		new ParserDelegator().parse(in, callback, false);
				
		return urls;
	}

	private List<String> parsePlainFile(URLConnection con) throws IOException  {
		//parsing the file, one line at a time
		BufferedReader in=new BufferedReader(new InputStreamReader(con.getInputStream()));
		String line=null;
		List<String> urls=new ArrayList<String>();
		while((line=in.readLine())!=null){
			try {
				URL testURL=new URL(line);
				//if we get here, it means the URL is ok
				//add it to the list
				urls.add(testURL.toString());
			} catch (MalformedURLException e) {/*ignored*/}			
		}
		in.close();
		return urls;
	}

	private void changeButtonsState(){
		if(currentlySelectedTask==null){
			return;
		}
		if(currentlySelectedTask.isComplete()){
			start_pauseDldButton.setSelected(false);
			start_pauseDldButton.setEnabled(false);
			start_pauseDldButton.setToolTipText("");
		}
		if(!currentlySelectedTask.isStarted()){
			start_pauseDldButton.setSelected(false);
			start_pauseDldButton.setToolTipText("Start download");
		}
		if(currentlySelectedTask.isStarted()&&!currentlySelectedTask.isComplete()){
			start_pauseDldButton.setSelected(true);
			start_pauseDldButton.setToolTipText("Pause download");
		}					
	}
	
	private void removeSelectedDownload(){
		if(currentlySelectedTask==null){
			return;
		}		
		listView.removeDownloadTask(currentlySelectedTask);
		if(!currentlySelectedTask.isComplete()){
			currentlySelectedTask.setStatus("Paused");
			currentlySelectedTask.setStarted(false);
			currentlySelectedTask.stopDownload();
		}
		DownloadManager.removeDownloadTask(currentlySelectedTask);
		DownloadManager.saveDownloadList(PreferencesManager.getDownloadListDatabase());
	}

	private void newDownload(){
		AddDownloadDialog dialog=new AddDownloadDialog(JOptionPane.getFrameForComponent(this),"Add Download",true,false);
		dialog.setLocationRelativeTo(this);
		dialog.setVisible(true);
		DownloadTask task=dialog.getDownloadTask();
		if(task!=null){			
			DownloadManager.addDownloadTask(task);
			DownloadManager.saveDownloadList(PreferencesManager.getDownloadListDatabase());
		}
	}
	
	public int getDividerLocation() {
		return splitPane.getDividerLocation();
	}

}
